package logic

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"time"

	"github.com/jung-kurt/gofpdf"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
)

// 心率数据结构
type HeartRateData struct {
	DeviceId  string    `bson:"device_id"`
	HeartRate int       `bson:"heart_rate"`
	Timestamp time.Time `bson:"timestamp"`
}

// 血压数据结构
type BloodPressureData struct {
	DeviceId  string    `bson:"device_id"`
	Systolic  int       `bson:"systolic"`
	Diastolic int       `bson:"diastolic"`
	Timestamp time.Time `bson:"timestamp"`
}

type HealthReport struct {
	DeviceId     string    `bson:"device_id"`
	StartDate    time.Time `bson:"start_date"`
	EndDate      time.Time `bson:"end_date"`
	AvgHeartRate float64   `bson:"avg_heart_rate"`
	MaxHeartRate int       `bson:"max_heart_rate"`
	MinHeartRate int       `bson:"min_heart_rate"`
	AvgSystolic  float64   `bson:"avg_systolic"`
	AvgDiastolic float64   `bson:"avg_diastolic"`
	MaxSystolic  int       `bson:"max_systolic"`
	MinSystolic  int       `bson:"min_systolic"`
	MaxDiastolic int       `bson:"max_diastolic"`
	MinDiastolic int       `bson:"min_diastolic"`
	ReportDate   time.Time `bson:"report_date"`
}

// 数据清洗函数，过滤掉脏数据并从数据库中删除
func cleanHeartRates(mongoClient *mongo.Client, deviceId string, data []HeartRateData) []HeartRateData {
	var cleaned []HeartRateData
	var toDelete []interface{}
	for _, d := range data {
		if d.HeartRate >= 30 && d.HeartRate <= 220 { // 合理心率范围
			cleaned = append(cleaned, d)
		} else {
			toDelete = append(toDelete, d.Timestamp)
		}
	}
	// 删除脏数据
	if len(toDelete) > 0 {
		coll := mongoClient.Database("health_monitor").Collection("heart_rate")
		for _, ts := range toDelete {
			coll.DeleteOne(context.Background(), bson.M{"device_id": deviceId, "timestamp": ts})
		}
	}
	return cleaned
}

func cleanBloodPressures(mongoClient *mongo.Client, DeviceId string, data []BloodPressureData) []BloodPressureData {
	var cleaned []BloodPressureData
	var toDelete []interface{}
	for _, d := range data {
		if d.Systolic >= 40 && d.Systolic <= 250 && d.Diastolic >= 30 && d.Diastolic <= 150 && d.Systolic > d.Diastolic {
			cleaned = append(cleaned, d)
		} else {
			toDelete = append(toDelete, d.Timestamp)
		}
	}
	// 删除脏数据
	if len(toDelete) > 0 {
		coll := mongoClient.Database("health_monitor").Collection("blood_pressure")
		for _, ts := range toDelete {
			coll.DeleteOne(context.Background(), bson.M{"device_id": DeviceId, "timestamp": ts})
		}
	}
	return cleaned
}

func GenerateHealthReport(mongoClient *mongo.Client, DeviceId string, startDate, endDate time.Time) (*HealthReport, error) {
	ctx := context.Background()
	// 查询心率数据
	hrColl := mongoClient.Database("health_monitor").Collection("heart_rate")
	hrCursor, err := hrColl.Find(ctx, bson.M{
		"equipment_id": DeviceId,
		"timestamp":    bson.M{"$gte": startDate, "$lte": endDate.Add(24 * time.Hour)},
	})
	if err != nil {
		return nil, err
	}
	var hrData []HeartRateData
	err = hrCursor.All(ctx, &hrData)
	if err != nil {
		return nil, err
	}
	// 清洗心率数据并删除脏数据
	hrData = cleanHeartRates(mongoClient, DeviceId, hrData)

	// 查询血压数据
	bpColl := mongoClient.Database("health_monitor").Collection("blood_pressure")
	bpCursor, err := bpColl.Find(ctx, bson.M{
		"equipment_id": DeviceId,
		"timestamp":    bson.M{"$gte": startDate, "$lte": endDate.Add(24 * time.Hour)},
	})
	if err != nil {
		return nil, err
	}
	var bpData []BloodPressureData
	err = bpCursor.All(ctx, &bpData)
	if err != nil {
		return nil, err
	}
	// 清洗血压数据并删除脏数据
	bpData = cleanBloodPressures(mongoClient, DeviceId, bpData)

	// 计算心率统计
	var avgHR float64
	var maxHR, minHR int
	if len(hrData) > 0 {
		maxHR, minHR = hrData[0].HeartRate, hrData[0].HeartRate
		var sum int
		for _, d := range hrData {
			sum += d.HeartRate
			if d.HeartRate > maxHR {
				maxHR = d.HeartRate
			}
			if d.HeartRate < minHR {
				minHR = d.HeartRate
			}
		}
		avgHR = float64(sum) / float64(len(hrData))
	}

	// 计算血压统计
	var avgSys, avgDia float64
	var maxSys, minSys, maxDia, minDia int
	if len(bpData) > 0 {
		maxSys, minSys = bpData[0].Systolic, bpData[0].Systolic
		maxDia, minDia = bpData[0].Diastolic, bpData[0].Diastolic
		var sumSys, sumDia int
		for _, d := range bpData {
			sumSys += d.Systolic
			sumDia += d.Diastolic
			if d.Systolic > maxSys {
				maxSys = d.Systolic
			}
			if d.Systolic < minSys {
				minSys = d.Systolic
			}
			if d.Diastolic > maxDia {
				maxDia = d.Diastolic
			}
			if d.Diastolic < minDia {
				minDia = d.Diastolic
			}
		}
		avgSys = float64(sumSys) / float64(len(bpData))
		avgDia = float64(sumDia) / float64(len(bpData))
	}

	report := &HealthReport{
		DeviceId:     DeviceId,
		StartDate:    startDate,
		EndDate:      endDate,
		AvgHeartRate: avgHR,
		MaxHeartRate: maxHR,
		MinHeartRate: minHR,
		AvgSystolic:  avgSys,
		AvgDiastolic: avgDia,
		MaxSystolic:  maxSys,
		MinSystolic:  minSys,
		MaxDiastolic: maxDia,
		MinDiastolic: minDia,
		ReportDate:   time.Now(),
	}

	return report, nil
}

// 生成健康建议
func generateAdvice(report *HealthReport) string {
	advice := ""
	// 心率建议
	if report.AvgHeartRate > 0 {
		if report.AvgHeartRate < 60 {
			advice += "平均心率偏低，建议注意休息，适当锻炼，必要时就医。\n"
		} else if report.AvgHeartRate > 100 {
			advice += "平均心率偏高，建议减少压力，避免过度劳累，必要时就医。\n"
		} else {
			advice += "心率正常，继续保持健康生活习惯。\n"
		}
	}
	// 收缩压建议
	if report.AvgSystolic > 0 {
		if report.AvgSystolic < 90 {
			advice += "平均收缩压偏低，注意补充水分和营养，必要时就医。\n"
		} else if report.AvgSystolic > 140 {
			advice += "平均收缩压偏高，建议减少盐分摄入，保持良好作息，必要时就医。\n"
		} else {
			advice += "收缩压正常，继续保持。\n"
		}
	}
	// 舒张压建议
	if report.AvgDiastolic > 0 {
		if report.AvgDiastolic < 60 {
			advice += "平均舒张压偏低，注意休息和营养，必要时就医。\n"
		} else if report.AvgDiastolic > 90 {
			advice += "平均舒张压偏高，建议适当锻炼，保持心情愉快，必要时就医。\n"
		} else {
			advice += "舒张压正常，继续保持。\n"
		}
	}
	return advice
}

func GeneratePDF(report *HealthReport) (string, error) {
	pdf := gofpdf.New("P", "mm", "A4", "")
	pdf.AddUTF8Font("msyh", "", "../common/fonts/simhei.ttf") // 你可以根据实际字体名调整
	pdf.AddPage()
	pdf.SetFont("msyh", "", 16)

	// 标题
	pdf.Cell(190, 10, "健康报告")
	pdf.Ln(10)

	// 基本信息
	pdf.SetFont("msyh", "", 12)
	pdf.Cell(190, 10, fmt.Sprintf("设备编号: %s", report.DeviceId))
	pdf.Ln(10)
	pdf.Cell(190, 10, fmt.Sprintf("统计区间: %s 到 %s", report.StartDate.Format("2006-01-02"), report.EndDate.Format("2006-01-02")))
	pdf.Ln(10)
	pdf.Cell(190, 10, fmt.Sprintf("报告生成时间: %s", report.ReportDate.Format("2006-01-02 15:04:05")))
	pdf.Ln(10)

	// 心率数据
	pdf.SetFont("msyh", "", 14)
	pdf.Cell(190, 10, "心率统计")
	pdf.Ln(10)
	pdf.SetFont("msyh", "", 12)
	pdf.Cell(190, 10, fmt.Sprintf("平均心率: %.1f bpm", report.AvgHeartRate))
	pdf.Ln(10)
	pdf.Cell(190, 10, fmt.Sprintf("最大心率: %d bpm", report.MaxHeartRate))
	pdf.Ln(10)
	pdf.Cell(190, 10, fmt.Sprintf("最小心率: %d bpm", report.MinHeartRate))
	pdf.Ln(10)

	// 血压数据
	pdf.SetFont("msyh", "", 14)
	pdf.Cell(190, 10, "血压统计")
	pdf.Ln(10)
	pdf.SetFont("msyh", "", 12)
	pdf.Cell(190, 10, fmt.Sprintf("平均收缩压: %.1f mmHg", report.AvgSystolic))
	pdf.Ln(10)
	pdf.Cell(190, 10, fmt.Sprintf("平均舒张压: %.1f mmHg", report.AvgDiastolic))
	pdf.Ln(10)
	pdf.Cell(190, 10, fmt.Sprintf("收缩压范围: %d - %d mmHg", report.MinSystolic, report.MaxSystolic))
	pdf.Ln(10)
	pdf.Cell(190, 10, fmt.Sprintf("舒张压范围: %d - %d mmHg", report.MinDiastolic, report.MaxDiastolic))
	pdf.Ln(10)

	// 健康建议
	pdf.SetFont("msyh", "", 14)
	pdf.Cell(190, 10, "健康建议")
	pdf.Ln(10)
	pdf.SetFont("msyh", "", 12)
	advice := generateAdvice(report)
	for _, line := range splitLines(advice) {
		pdf.MultiCell(190, 10, line, "", "", false)
		pdf.Ln(8)
	}

	// 创建 downloads 目录如果不存在
	err := os.MkdirAll("downloads", os.ModePerm)
	if err != nil {
		return "", fmt.Errorf("无法创建下载目录: %v", err)
	}

	// 保存PDF文件到 downloads 目录
	filename := fmt.Sprintf("health_report_%s_%s_%d.pdf", report.DeviceId, report.ReportDate.Format("20060102"), time.Now().UnixNano())
	join := filepath.Join("downloads", filename) // 保存到 downloads 目录下
	err = pdf.OutputFileAndClose(join)
	if err != nil {
		return "", fmt.Errorf("无法保存PDF文件: %v", err)
	}

	// 返回相对路径
	return join, nil
}

// 工具函数：按换行符分割建议文本
func splitLines(s string) []string {
	var lines []string
	start := 0
	for i, c := range s {
		if c == '\n' {
			lines = append(lines, s[start:i])
			start = i + 1
		}
	}
	if start < len(s) {
		lines = append(lines, s[start:])
	}
	return lines
}
